home *** CD-ROM | disk | FTP | other *** search
- /************************************************************************/
- /* */
- /* Cursor Control routines */
- /* */
- /* -- THINK C (V 4.0) version by Eric H. Seale, 1/23/90 */
- /* */
- /* Based on Lightspeed Pascal code by Chris Reed of San Angelo, */
- /* TX, and Yasser Farra of Austin, TX */
- /* */
- /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
- /* */
- /* CREDITS: */
- /* */
- /* Chris Reed -- original idea, simple implementation */
- /* */
- /* Yasser Farra -- improved exception handling, remove use of */
- /* buggy "SetUpA5" & "RestoreA5" routines (see tech note */
- /* 208), animation speed and "acur" resource ID are now */
- /* parameters */
- /* */
- /* Eric Seale -- translate to THINK C (from Lightspeed Pascal), */
- /* "flesh out" the documentation */
- /* */
- /************************************************************************/
- #include <VRetraceMgr.h>
-
-
-
-
-
-
- /************************************************************************/
- /* */
- /* Define some new data types to handle the cursor frames */
- /* */
- /************************************************************************/
- typedef struct {
- int frameCount; /* number of frames in animation sequence */
- int whichFrame; /* current frame number */
- CursHandle frame[]; /* list of "CURS" resources */
- } acur;
-
- typedef acur *acurPtr;
- typedef acurPtr *acurHandle;
-
-
-
-
-
-
-
- /************************************************************************/
- /* */
- /* Define some "global" variables for our use */
- /* */
- /************************************************************************/
- acurHandle frameList; /* handle to "acur" resource */
- VBLTask cursVBL; /* VBL task to handle cursor animation */
- Boolean cursAnimationEnabled, /* able to load "acur" and "CURS" rsrc's */
- cursAlreadyOn; /* cursor animation already running */
- int cursSpeed; /* # ticks between consec. frames */
-
-
-
-
-
-
-
-
- /************************************************************************/
- /* */
- /* Function Prototypes for our code here */
- /* */
- /************************************************************************/
-
- pascal long NuSetUpA5(void);
-
- pascal long NuRestoreA5(long);
-
- SetWatchCursor(void);
-
- InitCursAnimation (int);
-
- CursorAnimationVBL(void);
-
- AnimateCursor (int);
-
- StopCursor(void);
-
-
-
-
-
-
-
- pascal long NuSetUpA5(void)
- /************************************************************************/
- /* */
- /* pascal long NuSetUpA5(void) */
- /* -- This routine sets up the A5 to point to the boundary */
- /* between the application globals and the application */
- /* parameters. It returns the previous value of A5. This */
- /* function is used instead of SetUpA5 which is dangerous as it */
- /* does not return the old value of A5 but rather leaves it on */
- /* the stack--see tech note #208 for more details */
- /* */
- /* Note that both the Tech Note and Yasser's Pascal code called this */
- /* routine "SetCurrentA5" -- it seemed that since this replaces the */
- /* routine "SetUpA5," a more "intuitively obvious" name could be used */
- /* (makes life easier for those used to the old names). Also, note */
- /* that the assembler "equivalents" for the inline code are from */
- /* Apple's Tech Note -- I'm no assembly language whiz, so I can't */
- /* vouch for its accuracy (I just know that the hex works fine). */
- /* */
- /************************************************************************/
- = {
- 0x2E8D, /* move.l a5, 4(a7) */
- 0x2A78, /* move.l currentA5, a5 */
- 0x0904 /* rts */
- };
-
-
-
-
-
-
- pascal long NuRestoreA5(long newA5)
- /************************************************************************/
- /* */
- /* pascal long NuRestoreA5(long) */
- /* -- This routine sets the value of A5 to "newA5". It should be */
- /* used to restore the old value of A5 at the end of a */
- /* completion routine or a VBL task. It also returns the */
- /* previous value of A5. This function is used instead of */
- /* RestoreA5 which assumes the old value of A5 is still on the */
- /* stack--see tech note #208 for more details */
- /* */
- /* Note that both the Tech Note and Yasser's Pascal code called this */
- /* routine "SetA5" -- change the name back if you'd like. */
- /* */
- /************************************************************************/
- = {
- 0x2F4D, /* move.l (a7)+a0 */
- 0x0004, /* move.l a5, 4(a7) */
- 0x2A5F /* move.l (a7)+, a5 */
- }; /* jmp.l (a0) */
-
-
-
-
-
-
-
-
-
- SetWatchCursor()
- /************************************************************************/
- /* */
- /* SetWatchCursor(void) */
- /* -- set cursor to standard "watch" (cursor animation is disabled)*/
- /* */
- /************************************************************************/
- {
- CursHandle myCursor;
-
- myCursor = GetCursor(watchCursor);
- SetCursor(*myCursor);
- }
-
-
-
-
-
-
-
-
- InitCursAnimation(acurID)
- int acurID; /* RSRC ID of "acur" resource */
- /************************************************************************/
- /* */
- /* InitCursAnimation(int) */
- /* -- This procedure tries to load the "acur" resource and if */
- /* found tries to load all the "CURS" resources listed in the */
- /* "acur" resource */
- /* */
- /************************************************************************/
- {
- int i,
- errorCode;
-
- /* Get the "acur" resource */
- frameList = (acurHandle)GetResource('acur', acurID);
- errorCode = ResError();
-
- if (frameList == 0L) errorCode = resNotFound;
-
- if (errorCode == noErr) {
- i = 0;
-
- while ((i < (**frameList).frameCount) && (errorCode == noErr)){
- /* Get the "CURS" resources whose ID's are in the high word */
- /* of the frame field. Store handle to these resources in */
- /* the same frame field */
- (**frameList).frame[i] =
- GetCursor( HiWord((long)((**frameList).frame[i])) );
- errorCode = ResError();
- if ((**frameList).frame[i] == 0L)
- errorCode |= resNotFound;
- i++;
- }
-
- (**frameList).whichFrame = 1; /* Set initial frame */
- }
-
- cursAnimationEnabled = (errorCode == noErr);/* True if no error found */
- }
-
-
-
-
-
-
-
-
- CursorAnimationVBL()
- /************************************************************************/
- /* */
- /* CursorAnimationVBL(void) */
- /* -- VBL routine to set the cursor to the next cursor in the */
- /* animation sequence */
- /* */
- /************************************************************************/
- {
- long oldA5;
-
- oldA5 = NuSetUpA5();
-
- /* frameList and all frame handles are assumed to be locked */
- SetCursor(*((**frameList).frame[(**frameList).whichFrame]));
-
- if (++(**frameList).whichFrame >= (**frameList).frameCount)
- (**frameList).whichFrame = 1;
-
- cursVBL.vblCount = cursSpeed; /* Reinstall the VBL */
-
- oldA5 = NuRestoreA5(oldA5);
- }
-
-
-
-
-
-
-
- AnimateCursor(speed)
- int speed; /* Ticks between consecutive frames */
- /************************************************************************/
- /* */
- /* AnimateCursor(int) */
- /* -- Install our task in the vertical retrace queue unless cursor */
- /* animation is not enabled then use watch cursor */
- /* */
- /************************************************************************/
- {
- int errorcode, i;
-
- if (!cursAlreadyOn) {
- cursAlreadyOn = TRUE;
-
- if (cursAnimationEnabled) {
- /* Lock all handles that will be accessed from the VBL */
- HLock((Handle)(frameList));
- for (i=0; i<(**frameList).frameCount; i++)
- HLock((Handle)((**frameList).frame[i]));
-
- (**frameList).whichFrame = 1; /* Set initial frame */
-
- /* Set up the VBL task fields and install it */
- cursVBL.qType = vType;
- cursVBL.vblAddr = &CursorAnimationVBL;
- cursVBL.vblCount = speed; /* next VBL after "speed" ticks */
- cursVBL.vblPhase = 0;
-
- errorcode = VInstall(&cursVBL);
-
- cursSpeed = speed; /* Set the speed of animation */
- }
- else /* Use watch cursor */
- SetWatchCursor();
- }
- }
-
-
-
-
-
-
-
- StopCursor()
- /************************************************************************/
- /* */
- /* StopCursor(void) */
- /* -- Remove the VBL task from the vertical retrace queue and */
- /* restore the arrow cursor */
- /* */
- /************************************************************************/
- {
- int errorCode, i;
-
- if (cursAlreadyOn) {
- cursAlreadyOn = FALSE;
-
- if (cursAnimationEnabled) {
- errorCode = VRemove(&cursVBL);
-
- /* Unlock all handles that were locked before VBL */
- /* installation */
- HUnlock((Handle)(frameList));
- for (i = 0; i< (**frameList).frameCount; i++)
- HUnlock((Handle)((**frameList).frame[i]));
- }
-
- InitCursor();
- }
- }